package com.ctsi.hsph.spi.sync;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ctsi.hsph.contant.Constants;
import com.ctsi.hsph.spi.SpiService;
import com.ctsi.hsph.spi.dto.PingshuPositionDTO;
import com.ctsi.hsph.spi.dto.PingshuUserDTO;
import com.ctsi.hsph.spi.dto.PingshuUserSubPositionDTO;
import com.ctsi.sys.exceptions.BusinessException;
import com.ctsi.sys.mapper.*;
import com.ctsi.sys.po.*;
import com.ctsi.sys.util.RSAUtilNew;
import com.ctsi.sys.util.StringUtil;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 平数数据同步服务类
 */
@Slf4j
@Service
public class SyncService {
    // 默认
    private static final String PW = "ctsi@123";
    // 租户ID todo 正式环境上线前需要和正式库的check一下
    private static final Long TENANT_ID = 1879075484407435265L;
    // 默认 管理端 角色ID todo 正式环境上线前需要和正式库的check一下
    private static final Long DEFAULT_ADMIN_ROLE_ID = 1879075490262683649L;
    // 默认 企业端 角色ID todo 正式环境上线前需要和正式库的check一下
    private static final Long DEFAULT_ROLE_ID = 1879075490262683647L;
    // 默认parentId
    private static final Long DEFAULT_PARENT_ID = 0L;
    // 根机组织
    private static final String ROOT_ORG_NAME = "平湖市交通运输局";
    // 平湖市交通运输局Id
    private static final Long JTYS_DEPT_ID = 4630714536254046458L;
    // 同步限制
    private static final Integer SYNC_PAGE = 1;
    // 同步限制
    private static final Integer SYNC_LIMIT = 999;

    // 普通账号
    private static final String ACCOUNT_TYPE_NORMAL = "1";

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Resource
    JtUserMapper jtUserMapper;

    @Resource
    JtUserDetailMapper jtUserDetailMapper;

    @Resource
    JtUserRoleMapper jtUserRoleMapper;

    // 第一层属于机构
    @Resource
    JtOrgMapper jtOrgMapper;

    // 从第二层开始属于部门
    @Resource
    JtDeptMapper jtDeptMapper;

    @Autowired
    private SpiService spiService;

    /**
     * 同步机构和部门数据
     */
    @Transactional(rollbackFor = Exception.class)
    //@Scheduled(cron = "0 0/1 * * * ?")
    public void syncOrgAndDeptData() {
        try {
            // 分页拉取全部数据
            int pageNum = SYNC_PAGE;
            int pageSize = SYNC_LIMIT;
            List<PingshuPositionDTO> allDeptList = new ArrayList<>();

            while (true) {
                Map<String, Object> params = new HashMap<>();
                params.put("pageNum", pageNum);
                params.put("pageSize", pageSize);

                String orgAndDeptDataStr = spiService.getDeptList(params);
                JSONObject json = JSONUtil.parseObj(orgAndDeptDataStr);
                JSONArray dataArray = json.getJSONArray("data");

                if (dataArray == null || dataArray.isEmpty()) {
                    // 没数据，提前退出
                    break;
                }

                List<PingshuPositionDTO> pageList = JSONUtil.toList(dataArray, PingshuPositionDTO.class);
                allDeptList.addAll(pageList);

                System.out.println("第 " + pageNum + " 页拉取完成，记录数: " + pageList.size());

                if (pageList.size() < pageSize) {
                    // 最后一页
                    break;
                }

                pageNum++;
            }

            System.out.println("全部数据拉取完成，总记录数: " + allDeptList.size());

            // 1. 同步机构（原逻辑）
            List<JtOrgEntity> orgList = Lists.newArrayList();
            for (PingshuPositionDTO dto : allDeptList) {
                String path = dto.getPath();
                if (StringUtil.isEmpty(path)) continue;
                if (!path.contains("/") || path.length() - path.replace("/", "").length() == 1) {
                    JtOrgEntity jtOrgEntity = new JtOrgEntity();
                    jtOrgEntity.setId(convertToNumericKey(dto.getDeptCode()));
                    jtOrgEntity.setOrgName(dto.getDeptName());
                    jtOrgEntity.setTenantId(TENANT_ID);
                    jtOrgEntity.setParentId(DEFAULT_PARENT_ID);
                    jtOrgEntity.setStatus(Constants.ACCOUNT_ENABLED);
                    jtOrgEntity.setDescription(dto.getDepartment());
                    orgList.add(jtOrgEntity);
                }
            }
            for (JtOrgEntity jtOrgEntity : orgList) {
                JtOrgEntity entity = jtOrgMapper.selectById(jtOrgEntity.getId());
                if (entity == null) jtOrgMapper.insert(jtOrgEntity);
                else jtOrgMapper.updateById(jtOrgEntity);
            }

            // 2. 构建 parentMap 和 deptCodeMap
            Map<String, List<PingshuPositionDTO>> parentMap = new HashMap<>();
            Map<String, PingshuPositionDTO> deptCodeMap = new HashMap<>();
            for (PingshuPositionDTO dto : allDeptList) {
                if (StringUtil.isNotEmpty(dto.getParentCode())) {
                    parentMap.computeIfAbsent(dto.getParentCode(), k -> new ArrayList<>()).add(dto);
                }
                deptCodeMap.put(dto.getDeptCode(), dto);
            }

            // 同步的节点为 “平湖市交通运输局”
            String rootParentCode = "GO_ade3bc713fc146f0aa6620c1b8d22312";

            Set<String> visited = new HashSet<>();
            List<PingshuPositionDTO> resultList = new ArrayList<>();

            // 打印检查这个parentCode下是否有子部门
            System.out.println("开始同步 parentCode = " + rootParentCode);
            System.out.println("子部门数量（直接） = " + parentMap.getOrDefault(rootParentCode, Collections.emptyList()).size());

            // 添加根节点自身
            if (deptCodeMap.containsKey(rootParentCode)) {
                PingshuPositionDTO rootDto = deptCodeMap.get(rootParentCode);
                System.out.println("已加入根节点: " + rootDto.getDeptName() + "（" + rootDto.getDeptCode() + "）");
                resultList.add(rootDto);
                visited.add(rootParentCode);
            } else {
                System.out.println("警告：未找到指定 deptCode 对应的节点: " + rootParentCode);
            }

            // 开始递归添加子部门
            collectDepartmentsRecursive(rootParentCode, parentMap, resultList, visited);

            // 打印收集到的所有节点
            System.out.println("共收集到部门总数: " + resultList.size());
            for (PingshuPositionDTO dto : resultList) {
                System.out.println("收集到部门: " + dto.getDeptName() + "，deptCode=" + dto.getDeptCode() +
                        "，parentCode=" + dto.getParentCode());
            }

            // 构建实体并打印
            List<JtDeptEntity> deptEntities = new ArrayList<>();
            for (PingshuPositionDTO dto : resultList) {
                long deptId = convertToNumericKey(dto.getDeptCode());
                long parentId = StringUtil.isEmpty(dto.getParentCode()) ?
                        DEFAULT_PARENT_ID : convertToNumericKey(dto.getParentCode());

                JtDeptEntity dept = new JtDeptEntity();
                dept.setDeptId(deptId);
                dept.setDeptName(dto.getDeptName());
                dept.setTenantId(TENANT_ID);
                dept.setStatus(Constants.ACCOUNT_ENABLED);
                dept.setParentId(parentId);
                deptEntities.add(dept);

                // 打印即将写入的记录
                System.out.println("准备写入: " + dept.getDeptName() + "（deptId=" + deptId + "，parentId=" + parentId + "）");
            }

            // 写入数据库
            jtDeptMapper.saveOrUpdateBatch(deptEntities);

            log.info("同步完成：机构数量: {}, 部门数量: {}", orgList.size(), deptEntities.size());

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 递归收集指定 parentCode 下的所有部门（包括子孙节点）
     */
    private void collectDepartmentsRecursive(
            String parentCode,
            Map<String, List<PingshuPositionDTO>> parentMap,
            List<PingshuPositionDTO> result,
            Set<String> visited
    ) {
        List<PingshuPositionDTO> children = parentMap.get(parentCode);
        if (children == null) return;

        for (PingshuPositionDTO child : children) {
            if (visited.contains(child.getDeptCode())) continue;
            result.add(child);
            visited.add(child.getDeptCode());
            collectDepartmentsRecursive(child.getDeptCode(), parentMap, result, visited);
        }
    }

    /**
     * 处理部门的parentId
     *
     * @param path 部门路径
     * @return parentId
     */
    private Long handleParentId(String path) {
        if (StringUtil.isEmpty(path) || path.equals("/")) {
            return DEFAULT_PARENT_ID;
        }

        if (!path.contains("/")) {
            return DEFAULT_PARENT_ID;
        }

        String[] parts = path.split("/");
        String parentName = parts[parts.length - 2];

        return StringUtil.isEmpty(parentName) ? DEFAULT_PARENT_ID : convertToNumericKey(parentName);
    }

    /**
     * 同步用户数据
     */
    @Scheduled(cron = "0 29 19 * * ?")
//    @Scheduled(cron = "0 0/40 * * * ?")
    @Transactional(rollbackFor = Exception.class)
    public void syncUserData() {
        //JSONObject syncTotalDataObject;
        try {
            // 分页拉取用户数据
            int pageNum = SYNC_PAGE;
            int pageSize = SYNC_LIMIT;
            List<PingshuUserDTO> allUserList = new ArrayList<>();

            while (true) {
                Map<String, Object> params = new HashMap<>();
                params.put("pageNum", pageNum);
                params.put("pageSize", pageSize);

                String syncTotalStr = spiService.getUserList(params);
                JSONObject syncTotalJsonObject = JSONUtil.parseObj(syncTotalStr);
                JSONObject dataObj = syncTotalJsonObject.getJSONObject("data");

                if (dataObj == null || dataObj.getJSONArray("list") == null) {
                    break;
                }

                List<PingshuUserDTO> pageUserList = JSONUtil.toList(dataObj.getJSONArray("list"), PingshuUserDTO.class);
                List<PingshuUserDTO> tmp = new ArrayList<>();
                for (PingshuUserDTO pingshuUserDTO : pageUserList) {
                    List<PingshuUserSubPositionDTO> positions=pingshuUserDTO.getPositions();
                    for (PingshuUserSubPositionDTO position : positions) {
                        if ("平湖市交通运输局".equals(position.getThirdDeptName())){
                            tmp.add(pingshuUserDTO);
                            break;
                        }
                    }
                }
                allUserList.addAll(tmp);

                System.out.println("第 " + pageNum + " 页拉取完成，记录数: " + pageUserList.size());

                if (pageUserList.size() < pageSize) {
                    // 最后一页
                    break;
                }

                pageNum++;
            }

            System.out.println("用户数据拉取完成，总用户数: " + allUserList.size());

            // 定义存储新增的用户集合
            List<JtUserEntity> synAddUserList = Lists.newArrayList();
            List<JtUserDetailEntity> synAddUserDetailList = Lists.newArrayList();
            List<JtUserRoleEntity> userRoleList = Lists.newArrayList();

            for (PingshuUserDTO pingshuUserDTO : allUserList) {
//                // 机号为空跳过
//                if (StringUtil.isEmpty(pingshuUserDTO.getMobile())) {
//                    log.warn("跳过用户：userId={}, username={}，原因：手机号为空", pingshuUserDTO.getUserId(), pingshuUserDTO.getUsername());
//                    continue;
//                }

                Long hashedUserId = convertToNumericKey(pingshuUserDTO.getUserId());
                JtUserEntity existingUser = jtUserMapper.selectById(hashedUserId);

                if (existingUser == null) {
                    // 用户
                    JtUserEntity newUser = new JtUserEntity();
                    newUser.setId(hashedUserId);
                    newUser.setUsername(pingshuUserDTO.getMobile() == null ? pingshuUserDTO.getUsername() : pingshuUserDTO.getMobile());
                    newUser.setPassword(this.passwordEncoder.encode(PW));
                    newUser.setPassword1(RSAUtilNew.encrypt(PW));
                    synAddUserList.add(newUser);

                    // 用户详情
                    JtUserDetailEntity userDetail = new JtUserDetailEntity();
                    userDetail.setUserId(hashedUserId);
                    userDetail.setCreator("门户同步");
                    userDetail.setTenantId(TENANT_ID);
                    userDetail.setName(pingshuUserDTO.getUsername());
                    userDetail.setUserName(pingshuUserDTO.getUsername());
                    userDetail.setMobile(pingshuUserDTO.getMobile());
                    userDetail.setIsEnable(Constants.ACCOUNT_ENABLED);
                    userDetail.setAccountType(ACCOUNT_TYPE_NORMAL);

                    List<PingshuUserSubPositionDTO> positions = pingshuUserDTO.getPositions();
                    Long roleId = positionsMapToRole(positions);
                    JtUserRoleEntity jtUserRoleEntity = new JtUserRoleEntity();
                    jtUserRoleEntity.setUserId(hashedUserId);
                    jtUserRoleEntity.setRoleId(roleId);
                    userRoleList.add(jtUserRoleEntity);

                    if (CollectionUtil.isNotEmpty(positions)) {
                        PingshuUserSubPositionDTO positionDTO = positions.get(0);
                        String deptCode = positionDTO.getDeptCode();
                        long deptId = convertToNumericKey(deptCode);
                        userDetail.setDeptId(String.valueOf(deptId));
                        userDetail.setOrgId(String.valueOf(JTYS_DEPT_ID));
//                        try {
//                            String department = positionDTO.getDepartment();
//                            if (StringUtil.isNotEmpty(department)) {
//                                int index = department.indexOf("-");
//                                if (index != -1) {
//                                    department = department.substring(0, index);
//                                }
//                                LambdaQueryWrapper<JtOrgEntity> orgQuery = new LambdaQueryWrapper<>();
//                                orgQuery.eq(JtOrgEntity::getOrgName, department);
//                                JtOrgEntity orgEntity = jtOrgMapper.selectOne(orgQuery);
//                                if (orgEntity != null) {
//                                    userDetail.setOrgId(String.valueOf(orgEntity.getId()));
//                                }
//                            }
//                        } catch (Exception e) {
//                            log.error("处理部门字符串时出错: {}", e.getMessage());
//                        }
                    }

                    synAddUserDetailList.add(userDetail);
                }
            }

            // 插入数据
            jtUserMapper.insertBatch(synAddUserList);
            jtUserDetailMapper.insertBatch(synAddUserDetailList);

            // 删除旧角色并插入新角色
            Set<Long> userIds = userRoleList.stream().map(JtUserRoleEntity::getUserId).collect(Collectors.toSet());
            for (Long userId : userIds) {
                LambdaQueryWrapper<JtUserRoleEntity> delQuery = new LambdaQueryWrapper<>();
                delQuery.eq(JtUserRoleEntity::getUserId, userId);
                jtUserRoleMapper.delete(delQuery);
            }
            for (JtUserRoleEntity jtUserRoleEntity : userRoleList) {
                jtUserRoleMapper.insert(jtUserRoleEntity);
            }

            log.info("同步用户数据完成，新增用户: {}，详情: {}，角色: {}", synAddUserList.size(), synAddUserDetailList.size(), userRoleList.size());

        } catch (Exception e) {
            log.error("同步用户数据失败: {}", e.getMessage());
            throw new BusinessException("同步用户数据失败");
        }
    }


    /**
     * 根据用户的职位列表映射到角色ID。
     * 目前假设每个用户只有一个角色，且角色ID是通过职位名称来确定的。
     *
     * @param positions 用户的职位列表
     * @return 映射后的角色ID
     */
    private Long positionsMapToRole(List<PingshuUserSubPositionDTO> positions) {
        if (CollectionUtil.isEmpty(positions)) {
            return DEFAULT_ROLE_ID; // 如果没有职位信息，返回默认角色ID
        }
        if (positions.stream().anyMatch(x -> StringUtil.isNotEmpty(x.getDepartment()) && x.getDepartment().startsWith(ROOT_ORG_NAME))) {
            return DEFAULT_ADMIN_ROLE_ID;
        }
        return DEFAULT_ROLE_ID; // 默认角色ID
    }

    /**
     * 将字符串转换为一个长整型数字。
     * 使用 SHA-256 哈希算法来生成一个唯一的数字键。
     *
     * @param input 输入字符串
     * @return 转换后的长整型数字
     */
    public static long convertToNumericKey(String input) {
        try {
            // 选择 SHA-256 哈希算法
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(input.getBytes());

            // 将哈希数组转换为一个长整型数字
            long numericKey = 0;
            for (int i = 0; i < 8; i++) { // 取前8个字节
                numericKey = (numericKey << 8) | (hash[i] & 0xFF);
            }
            log.info("转换字符串 '{}' 为数字键: {}", input, numericKey);
            return Math.abs(numericKey); // 确保是正数
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }
}
